home *** CD-ROM | disk | FTP | other *** search
/ InterCD 2000 September / september_2000.iso / intercd / root / ^Linux / WindowMaker / wrlib / raster.c < prev    next >
Encoding:
C/C++ Source or Header  |  2000-03-06  |  12.5 KB  |  555 lines

  1. /* raster.c - main and other misc stuff 
  2.  * 
  3.  *  Raster graphics library
  4.  * 
  5.  *  Copyright (c) 1997-2000 Alfredo K. Kojima
  6.  *
  7.  *  This library is free software; you can redistribute it and/or
  8.  *  modify it under the terms of the GNU Library General Public
  9.  *  License as published by the Free Software Foundation; either
  10.  *  version 2 of the License, or (at your option) any later version.
  11.  *  
  12.  *  This library is distributed in the hope that it will be useful,
  13.  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
  14.  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  15.  *  Library General Public License for more details.
  16.  *  
  17.  *  You should have received a copy of the GNU Library General Public
  18.  *  License along with this library; if not, write to the Free
  19.  *  Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  20.  */
  21.  
  22. #include <config.h>
  23.  
  24. #include <stdlib.h>
  25. #include <stdio.h>
  26. #include <string.h>
  27. #include <X11/Xlib.h>
  28. #include "wraster.h"
  29.  
  30. #include <assert.h>
  31.  
  32.  
  33. char *WRasterLibVersion="0.9";
  34.  
  35. int RErrorCode=RERR_NONE;
  36.  
  37.  
  38. #define HAS_ALPHA(I)    ((I)->format == RRGBAFormat)
  39.  
  40.  
  41. RImage*
  42. RCreateImage(unsigned width, unsigned height, int alpha)
  43. {
  44.     RImage *image=NULL;
  45.     
  46.     assert(width>0 && height>0);
  47.  
  48.     image = malloc(sizeof(RImage));
  49.     if (!image) {
  50.     RErrorCode = RERR_NOMEMORY;
  51.         return NULL;
  52.     }
  53.  
  54.     memset(image, 0, sizeof(RImage));
  55.     image->width = width;
  56.     image->height = height;
  57.     if (alpha) {
  58.     image->format = RRGBAFormat;
  59.     } else {
  60.     image->format = RRGBFormat;
  61.     }
  62.     /* the +4 is to give extra bytes at the end of the buffer,
  63.      * so that we can optimize image conversion for MMX(tm).. see convert.c
  64.      */
  65.     image->data = malloc(width * height * (alpha ? 4 : 3) + 4);
  66.     if (!image->data) {
  67.     RErrorCode = RERR_NOMEMORY;
  68.     free(image);
  69.     image = NULL;
  70.     }
  71.  
  72.     return image;
  73. }
  74.  
  75.  
  76.  
  77. RImage*
  78. RCloneImage(RImage *image)
  79. {
  80.     RImage *new_image;
  81.  
  82.     assert(image!=NULL);
  83.     
  84.     new_image = RCreateImage(image->width, image->height, HAS_ALPHA(image));
  85.     if (!new_image)
  86.       return NULL;
  87.     
  88.     new_image->background = image->background;
  89.     memcpy(new_image->data, image->data,
  90.        image->width*image->height*(HAS_ALPHA(image) ? 4 : 3));
  91.  
  92.     return new_image;
  93. }
  94.  
  95.  
  96. RImage*
  97. RGetSubImage(RImage *image, int x, int y, unsigned width, unsigned height)
  98. {
  99.     int i, ofs;
  100.     RImage *new_image;
  101.     unsigned total_line_size, line_size;
  102.     
  103.     assert(image!=NULL);
  104.     assert(x>=0 && y>=0);
  105.     assert(x<image->width && y<image->height);
  106.     assert(width>0 && height>0);
  107.     
  108.     if (x+width > image->width)
  109.     width = image->width-x;
  110.     if (y+height > image->height)
  111.     height = image->height-y;
  112.  
  113.     new_image = RCreateImage(width, height, HAS_ALPHA(image));
  114.  
  115.     if (!new_image)
  116.     return NULL;
  117.     new_image->background = image->background;
  118.  
  119.     total_line_size = image->width * (HAS_ALPHA(image) ? 4 : 3);
  120.     line_size = width * (HAS_ALPHA(image) ? 4 : 3);
  121.  
  122.     ofs = x*(HAS_ALPHA(image) ? 4 : 3) + y*total_line_size;;
  123.  
  124.     for (i=0; i<height; i++) {
  125.     memcpy(&new_image->data[i*line_size], 
  126.            &image->data[i*total_line_size+ofs], line_size);
  127.     }
  128.     return new_image;
  129. }
  130.  
  131.  
  132. void 
  133. RDestroyImage(RImage *image)
  134. {
  135.     assert(image!=NULL);
  136.  
  137.     free(image->data);
  138.     free(image);
  139. }
  140.  
  141.  
  142. /*
  143.  *---------------------------------------------------------------------- 
  144.  * RCombineImages-
  145.  *     Combines two equal sized images with alpha image. The second
  146.  * image will be placed on top of the first one.
  147.  *---------------------------------------------------------------------- 
  148.  */
  149. void
  150. RCombineImages(RImage *image, RImage *src)
  151. {
  152.     assert(image->width == src->width);
  153.     assert(image->height == src->height);
  154.  
  155.     if (!HAS_ALPHA(src)) {
  156.     if (!HAS_ALPHA(image)) {
  157.         memcpy(image->data, src->data, image->height*image->width*3);
  158.     } else {
  159.         int x, y;
  160.         unsigned char *d, *s;
  161.         
  162.         d = image->data;
  163.         s = src->data;
  164.         for (y = 0; y < image->height; y++) {
  165.         for (x = 0; x < image->width; x++) {
  166.             *d++ = *s++;
  167.             *d++ = *s++;
  168.             *d++ = *s++;
  169.             d++;
  170.         }
  171.         }
  172.     }
  173.     } else {
  174.     register int i;
  175.     unsigned char *d;
  176.     unsigned char *s;
  177.     int alpha, calpha;
  178.  
  179.     d = image->data;
  180.     s = src->data;
  181.  
  182.     if (!HAS_ALPHA(image)) {
  183.         for (i=0; i<image->height*image->width; i++) {
  184.         alpha = *(s+3);
  185.         calpha = 255 - alpha;
  186.         *d = (((int)*d * calpha) + ((int)*s * alpha))/256;
  187.         d++; s++;
  188.         *d = (((int)*d * calpha) + ((int)*s * alpha))/256;
  189.         d++; s++;
  190.         *d = (((int)*d * calpha) + ((int)*s * alpha))/256;
  191.         d++; s++;
  192.         s++;
  193.         }
  194.     } else {
  195.         for (i=0; i<image->height*image->width; i++) {
  196.         alpha = *(s+3);
  197.         calpha = 255 - alpha;
  198.         *d = (((int)*d * calpha) + ((int)*s * alpha))/256;
  199.         d++; s++;
  200.         *d = (((int)*d * calpha) + ((int)*s * alpha))/256;
  201.         d++; s++;
  202.         *d = (((int)*d * calpha) + ((int)*s * alpha))/256;
  203.         d++; s++;
  204.         *d++ |= *s++;
  205.         }
  206.     }
  207.     }
  208. }
  209.  
  210.  
  211.  
  212.  
  213. void
  214. RCombineImagesWithOpaqueness(RImage *image, RImage *src, int opaqueness)
  215. {
  216.     register int i;
  217.     unsigned char *d;
  218.     unsigned char *s;
  219.     int c_opaqueness;
  220.  
  221.     assert(image->width == src->width);
  222.     assert(image->height == src->height);
  223.  
  224.     d = image->data;
  225.     s = src->data;
  226.  
  227.     c_opaqueness = 255 - opaqueness;
  228. #define OP opaqueness
  229.     if (!HAS_ALPHA(src)) {
  230.     int dalpha = HAS_ALPHA(image);
  231. #define COP c_opaqueness
  232.     for (i=0; i < image->width*image->height; i++) {
  233.         *d = (((int)*d *(int)COP) + ((int)*s *(int)OP))/256;
  234.         d++; s++;
  235.         *d = (((int)*d *(int)COP) + ((int)*s *(int)OP))/256;
  236.         d++; s++;
  237.         *d = (((int)*d *(int)COP) + ((int)*s *(int)OP))/256;
  238.         d++; s++;
  239.         if (dalpha) {
  240.         d++;
  241.         }
  242.     }
  243. #undef COP
  244.     } else {
  245.     int tmp;
  246.  
  247.     if (!HAS_ALPHA(image)) {
  248.         for (i=0; i<image->width*image->height; i++) {
  249.         tmp = (*(s+3) * opaqueness)/256;
  250.         *d = (((int)*d * (255-tmp)) + ((int)*s * tmp))/256;
  251.         d++; s++;
  252.         *d = (((int)*d * (255-tmp)) + ((int)*s * tmp))/256;
  253.         d++; s++;
  254.         *d = (((int)*d * (255-tmp)) + ((int)*s * tmp))/256;
  255.         d++; s++;
  256.         s++;
  257.         }
  258.     } else {
  259.         for (i=0; i<image->width*image->height; i++) {
  260.         tmp = (*(s+3) * opaqueness)/256;
  261.         *d = (((int)*d * (255-tmp)) + ((int)*s * tmp))/256;
  262.         d++; s++;
  263.         *d = (((int)*d * (255-tmp)) + ((int)*s * tmp))/256;
  264.         d++; s++;
  265.         *d = (((int)*d * (255-tmp)) + ((int)*s * tmp))/256;
  266.         d++; s++;
  267.         *d |= tmp;
  268.         d++; s++;
  269.         }
  270.     }
  271.     }
  272. #undef OP
  273. }
  274.  
  275.  
  276. void
  277. RCombineArea(RImage *image, RImage *src, int sx, int sy, unsigned width,
  278.          unsigned height, int dx, int dy)
  279. {
  280.     int x, y, dwi, swi;
  281.     unsigned char *d;
  282.     unsigned char *s;
  283.     int alpha, calpha;
  284.  
  285.  
  286.     assert(dy < image->height);
  287.     assert(dx < image->width);
  288.  
  289.     assert(sy + height <= src->height);
  290.     assert(sx + width <= src->width);
  291.  
  292.     if (width > image->width - dx)
  293.     width = image->width - dx;
  294.  
  295.     if (height > image->height - dy)
  296.     height = image->height - dy;
  297.  
  298.     if (!HAS_ALPHA(src)) {
  299.     if (!HAS_ALPHA(image)) {
  300.         swi = src->width * 3;
  301.         dwi = image->width * 3;
  302.  
  303.         s = src->data + (sy*(int)src->width + sx) * 3;
  304.         d = image->data + (dy*(int)image->width + dx) * 3;
  305.  
  306.         for (y=0; y < height; y++) {
  307.         memcpy(d, s, width*3);
  308.         d += dwi;
  309.         s += swi;
  310.         }
  311.     } else {
  312.         swi = (src->width - width) * 3;
  313.         dwi = (image->width - width) * 4;
  314.  
  315.         s = src->data + (sy*(int)src->width + sx) * 3;
  316.         d = image->data + (dy*(int)image->width + dx) * 4;
  317.  
  318.         for (y=0; y < height; y++) {
  319.         for (x=0; x < width; x++) {
  320.             *d++ = *s++;
  321.             *d++ = *s++;
  322.             *d++ = *s++;
  323.             d++;
  324.         }
  325.         d += dwi;
  326.         s += swi;
  327.         }
  328.     }
  329.     } else {
  330.     int dalpha = HAS_ALPHA(image);
  331.  
  332.     swi = (src->width - width) * 4;
  333.     s = src->data + (sy*(int)src->width + sx) * 4;
  334.     if (dalpha) {
  335.         dwi = (image->width - width) * 4;
  336.         d = image->data + (dy*(int)image->width + dx) * 4;
  337.     } else {
  338.         dwi = (image->width - width) * 3;
  339.         d = image->data + (dy*(int)image->width + dx) * 3;
  340.     }
  341.  
  342.     for (y=0; y < height; y++) {
  343.         for (x=0; x < width; x++) {
  344.         alpha = *(s+3);
  345.         calpha = 255 - alpha;
  346.         *d = (((int)*d * calpha) + ((int)*s * alpha))/256;
  347.         s++; d++;
  348.         *d = (((int)*d * calpha) + ((int)*s * alpha))/256;
  349.         s++; d++;
  350.         *d = (((int)*d * calpha) + ((int)*s * alpha))/256;
  351.         s++; d++;
  352.         s++;
  353.         if (dalpha)
  354.             d++;
  355.         }
  356.         d += dwi;
  357.         s += swi;
  358.     }
  359.     }
  360. }
  361.  
  362.  
  363. void
  364. RCombineAreaWithOpaqueness(RImage *image, RImage *src, int sx, int sy, 
  365.                unsigned width, unsigned height, int dx, int dy,
  366.                int opaqueness)
  367. {
  368.     int x, y, dwi, swi;
  369.     int c_opaqueness;
  370.     unsigned char *d;
  371.     unsigned char *s;
  372.     int dalpha = HAS_ALPHA(image);
  373.     int dch = (dalpha ? 4 : 3);
  374.  
  375.     assert(dy <= image->height);
  376.     assert(dx <= image->width);
  377.  
  378.     assert(sy <= height);
  379.     assert(sx <= width);
  380.  
  381.  
  382.     /* clip */
  383.     width -= sx;
  384.     height -= sy;
  385.  
  386.     if (height > image->height - dy)
  387.     height = image->height - dy;
  388.  
  389.     d = image->data + dy*image->width*dch + dx;
  390.     dwi = (image->width - width)*dch;
  391.  
  392.     c_opaqueness = 255 - opaqueness;
  393. #define OP opaqueness
  394.     if (!HAS_ALPHA(src)) {
  395. #define COP c_opaqueness
  396.  
  397.     s = src->data + sy*src->width*3;    
  398.     swi = (src->width - width) * 3;
  399.     
  400.     for (y=0; y < height; y++) {
  401.         for (x=0; x < width; x++) {
  402.         *d = (((int)*d *(int)COP) + ((int)*s *(int)OP))/256;
  403.         s++; d++;
  404.         *d = (((int)*d *(int)COP) + ((int)*s *(int)OP))/256;
  405.         s++; d++;
  406.         *d = (((int)*d *(int)COP) + ((int)*s *(int)OP))/256;
  407.         s++; d++;
  408.         if (dalpha)
  409.             d++;
  410.         }
  411.         d += dwi; s += swi;
  412.     }
  413. #undef COP
  414.     } else {
  415.         int tmp;
  416.  
  417.     s = src->data + sy*src->width*4;
  418.     swi = (src->width - width) * 4;
  419.     
  420.     for (y=0; y < height; y++) {
  421.         for (x=0; x < width; x++) {
  422.             tmp= (*(s+3) * opaqueness)/256;
  423.         *d = (((int)*d *(int)(255-tmp)) + ((int)*s *(int)tmp))/256;
  424.         d++; s++;
  425.         *d = (((int)*d *(int)(255-tmp)) + ((int)*s *(int)tmp))/256;
  426.         d++; s++;
  427.         *d = (((int)*d *(int)(255-tmp)) + ((int)*s *(int)tmp))/256;
  428.         d++; s++;
  429.         s++;
  430.         if (dalpha)
  431.             d++;
  432.         }
  433.         d += dwi; s += swi;
  434.     }
  435.     }
  436. #undef OP
  437. }            
  438.  
  439.  
  440.  
  441. void
  442. RCombineImageWithColor(RImage *image, RColor *color)
  443. {
  444.     register int i;
  445.     unsigned char *d;
  446.     int alpha, nalpha, r, g, b;
  447.  
  448.     d = image->data;
  449.     
  450.     if (!HAS_ALPHA(image)) {
  451.     /* Image has no alpha channel, so we consider it to be all 255.
  452.      * Thus there are no transparent parts to be filled. */
  453.     return;
  454.     }
  455.     r = color->red;
  456.     g = color->green;
  457.     b = color->blue;
  458.  
  459.     for (i=0; i < image->width*image->height; i++) {
  460.     alpha = *(d+3);
  461.     nalpha = 255 - alpha;
  462.  
  463.     *d = (((int)*d * alpha) + (r * nalpha))/256;
  464.     d++;
  465.     *d = (((int)*d * alpha) + (g * nalpha))/256;
  466.     d++;
  467.     *d = (((int)*d * alpha) + (b * nalpha))/256;
  468.     d++;
  469.     d++;
  470.     }
  471. }
  472.  
  473.  
  474.  
  475.  
  476. RImage*
  477. RMakeTiledImage(RImage *tile, unsigned width, unsigned height)
  478. {
  479.     int x, y;
  480.     unsigned w;
  481.     unsigned long tile_size = tile->width * tile->height;
  482.     unsigned long tx = 0;
  483.     RImage *image;
  484.     unsigned char *s, *d;
  485.  
  486.     if (width == tile->width && height == tile->height)
  487.         image = RCloneImage(tile);
  488.     else if (width <= tile->width && height <= tile->height)
  489.         image = RGetSubImage(tile, 0, 0, width, height);
  490.     else {
  491.     int has_alpha = HAS_ALPHA(tile);
  492.  
  493.         image = RCreateImage(width, height, has_alpha);
  494.  
  495.         d = image->data;
  496.         s = tile->data;
  497.  
  498.         for (y = 0; y < height; y++) {
  499.             for (x = 0; x < width; x += tile->width) {
  500.  
  501.                 w = (width - x < tile->width) ? width - x : tile->width;
  502.  
  503.         if (has_alpha) {
  504.             w *= 4;
  505.             memcpy(d, s+tx*4, w);
  506.         } else {
  507.             w *= 3;
  508.             memcpy(d, s+tx*3, w);
  509.         }
  510.                 d += w;
  511.             }
  512.         
  513.             tx = (tx + tile->width) % tile_size;
  514.         }
  515.     }
  516.     return image;
  517. }
  518.  
  519.  
  520. RImage*
  521. RMakeCenteredImage(RImage *image, unsigned width, unsigned height, RColor *color)
  522. {
  523.     int x, y, w, h, sx, sy;
  524.     RImage *tmp;
  525.  
  526.     tmp = RCreateImage(width, height, False);
  527.     if (!tmp) {
  528.         return NULL;
  529.     }
  530.  
  531.     RClearImage(tmp, color);
  532.  
  533.     if (image->height < height) {
  534.         h = image->height;
  535.         y = (height - h)/2;
  536.         sy = 0;
  537.     } else {
  538.         sy = (image->height - height)/2;
  539.         y = 0;
  540.         h = height;
  541.     }
  542.     if (image->width < width) {
  543.         w = image->width;
  544.         x = (width - w)/2;
  545.         sx = 0;
  546.     } else {
  547.         sx = (image->width - width)/2;
  548.         x = 0;
  549.         w = width;
  550.     }
  551.     RCombineArea(tmp, image, sx, sy, w, h, x, y);
  552.  
  553.     return tmp;
  554. }
  555.